from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

from typing import Generator
from contextlib import contextmanager

from config import GlobalContextData

engine = create_engine(GlobalContextData.DataBaseConnectionString)

class MetaData:
    create_all: callable

class DbBase:
    metadata: MetaData

class Database:
    Engine = engine
    Base: DbBase = declarative_base()

    @staticmethod
    def create_table_all():
        try:
            Database.Base.metadata.create_all(engine)
        except Exception as e:
            print(f'Database Exception: {GlobalContextData.DataBaseConnectionString=}, {e}')
            raise e

    @staticmethod
    def get_session() -> Session:
        try:
            return sessionmaker(bind=engine)()
        except Exception as e:
            print(f'Database Exception: {GlobalContextData.DataBaseConnectionString=}, {e}')
            raise e

    @staticmethod
    @contextmanager
    def open_session() -> Generator[Session, None, None]:
        session = Database.get_session()
        try:
            yield session
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            session.close()
